#include "stdafx.h"
#include "C2DGraphics.h"

C2DGraphics::C2DGraphics() 
{
}

C2DGraphics::~C2DGraphics()
{
}

int C2DGraphics::Initialize()
{
	return 1;
}

//Load a bitmap from disk. (To reload, first delete the old one then call this). The
//Direct3D surface will be invalid until the first time the bitmap is drawn, when
//the loaded bitmap gets copied into a newly created surface. This is so bitmaps can
//be preloaded before graphics are initialized. 
int C2DGraphics::LoadBitmapFromFile(const WCHAR *Filename, BitmapStruct *pBitmap)
{
	if (!pBitmap || pBitmap->hBitmap != NULL)
		return 0;

	//Load it
	pBitmap->hBitmap = (HBITMAP)LoadImage(NULL, Filename,IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
	if (pBitmap->hBitmap == NULL)
		return 0;
	
	//Get its size
	BITMAP BM;
	if (!GetObject(pBitmap->hBitmap, sizeof(BITMAP), &BM))
	{
		DeleteObject(pBitmap->hBitmap);
		pBitmap->hBitmap = NULL;
		return 0;
	}
	pBitmap->WidthPix = BM.bmWidth;
	pBitmap->HeightPix = BM.bmHeight;

	return 1;
}

//Draw the given bitmap to the given device. This reloads the surface if it's for a different device
//than previously drawn to, so if the same bitmap needs to be frequently drawn to different devices,
//it's better to have separate bitmaps, one for each device. But if drawing on different devices is
//infrequent, just calling this method with the new device should be sufficient. 
int C2DGraphics::DrawBitmap(IDirect3DDevice9* pDevice, BitmapStruct *pBitmap, long ScreenX, long ScreenY)
{
	if (!pDevice || pBitmap->hBitmap == NULL)
		return 0;
	
	//Is the device different than what the bitmap was made for?
	if (pBitmap->pDevice != pDevice)
	{
		if (!ReloadSurface(pBitmap, pDevice))
			return 0;
	}
	
	//Get the back buffer
	IDirect3DSurface9 *pBackBuffer = NULL;
	if (FAILED(pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer)))
		return 0;
	
	//Draw the surface onto it
	RECT r;
	r.left = ScreenX;
	r.top = ScreenY;
	r.right = ScreenX + pBitmap->WidthPix;
	r.bottom = ScreenY + pBitmap->HeightPix;
	HRESULT hr = pDevice->StretchRect(pBitmap->pSurface, NULL, pBackBuffer, &r, D3DTEXF_NONE);
	pBackBuffer->Release();
	if (FAILED(hr))
		return 0;
	return 1;
}

//Reload the cached bitmap into the surface, or if it's for a different device,
//create a new surface for that device and load the bitmap. 
int C2DGraphics::ReloadSurface(BitmapStruct *pBitmap, IDirect3DDevice9 *pDevice)
{
	//Is it a new device?
	if (pBitmap->pDevice != pDevice)
	{
		//Replace the previous device pointer with this new one
		if (pBitmap->pDevice)
			pBitmap->pDevice->Release();
		pBitmap->pDevice = pDevice;
		pBitmap->pDevice->AddRef();

		//Replace the previous surface with a new one created for this device
		if (pBitmap->pSurface)
			pBitmap->pSurface->Release();
		if (FAILED(pDevice->CreateOffscreenPlainSurface(pBitmap->WidthPix, pBitmap->HeightPix, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT,
			&pBitmap->pSurface, NULL)))
		{
			pBitmap->pSurface = NULL;
			return 0;
		}
	}

	//Copy in the cached bitmap
	HDC hDC;
	if (FAILED(pBitmap->pSurface->GetDC(&hDC)))
		return 0;
	HDC hCompat = CreateCompatibleDC(hDC);
	SelectObject(hCompat, pBitmap->hBitmap);
	BitBlt(hDC, 0, 0, pBitmap->WidthPix, pBitmap->HeightPix, hCompat, 0, 0, SRCCOPY);
	pBitmap->pSurface->ReleaseDC(hDC);
	ReleaseDC(NULL, hCompat);
	DeleteDC(hCompat);

	return 1;
}

int C2DGraphics::DeleteBitmap(BitmapStruct *pBitmap)
{
	if (pBitmap->hBitmap)
		DeleteObject(pBitmap->hBitmap);
	pBitmap->hBitmap = NULL;
	if (pBitmap->pDevice)
		pBitmap->pDevice->Release();
	pBitmap->pDevice = NULL;
	if (pBitmap->pSurface)
		pBitmap->pSurface->Release();
	pBitmap->pSurface = NULL;

	return 1;
}
	
int C2DGraphics::Shutdown()
{
	
	return 1;
}
